/*
 * HMSMenuList.java
 *
 * Created on January 13, 2006, 10:43 AM
 *
 * To change this template, choose Tools | Options and locate the template under
 * the Source Creation and Management node. Right-click the template and choose
 * Open. You can then make changes to the template in the Source Editor.
 */
package com.bff.slimserver.musicjukebox.ui.components;

import com.bff.bjj.ui.component.MusicList;
import com.bff.bjj.ui.component.MusicListCellRenderer;
import com.bff.slimserver.music.SongTransferable;
import com.bff.slimserver.music.exceptions.PlaylistException;
import com.bff.slimserver.musicjukebox.lib.JukeboxProperties;
import java.awt.Component;
import java.awt.Rectangle;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultListModel;
import javax.swing.DropMode;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.ListSelectionModel;
import javax.swing.TransferHandler;
import org.bff.slimserver.SlimPlaylist;
import org.bff.slimserver.exception.SlimException;
import org.bff.slimserver.musicobjects.SlimPlayableObject;
import org.bff.slimserver.musicobjects.SlimPlaylistItem;

/**
 *
 */
public class PlaylistSongList extends MusicList {

    private SlimPlaylist playlist;

    /** Creates a new instance of PlaylistSongList */
    public PlaylistSongList() {
        init();
    }

    public PlaylistSongList(Object[] listData) {
        super(listData);
        init();
    }

    public PlaylistSongList(DefaultListModel model) {
        super(model);
        init();
    }

    private void init() {
        try {
            playlist = JukeboxProperties.getInstance().getPlaylist();
        } catch (PlaylistException ex) {
            Logger.getLogger(PlaylistSongList.class.getName()).log(Level.SEVERE, null, ex);
        }

        setTransferHandler(new SongTransferHandler(TransferHandler.MOVE));
        setDropMode(DropMode.INSERT);
        setDragEnabled(true);
        setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        setCellRenderer(new MenuListCellRenderer());
    }

    private class MenuListCellRenderer extends MusicListCellRenderer {

        public MenuListCellRenderer() {
            setOpaque(true);
        }

        @Override
        public Component getListCellRendererComponent(JList list,
                Object value,
                int index,
                boolean isSelected,
                boolean isFocused) {

            if (value instanceof String) {
                setText(value.toString());
                setBorder(null);
            }

            setColors(list, index, isSelected);

            return (this);
        }
    }

    class SongTransferHandler extends TransferHandler {

        private int action;
        private int fromIndex;
        private int toIndex;

        public SongTransferHandler(int action) {
            this.action = action;
        }

        public int getSourceActions(JComponent comp) {
            return COPY_OR_MOVE;
        }

        public Transferable createTransferable(JComponent comp) {
            fromIndex = getSelectedIndex();
            if (getSelectedIndex() < 0 || getSelectedIndex() >= getModel().getSize()) {
                return null;
            }

            return new SongTransferable((SlimPlayableObject) getSelectedValue());
        }

        public void exportDone(JComponent comp, Transferable trans, int action) {
            if (action != MOVE) {
                return;
            }

            int index = -1;

            if (toIndex > fromIndex) {
                index = fromIndex;
            } else {
                index = fromIndex + 1;
            }
            ((DefaultListModel) getModel()).remove(index);
        }

        public boolean canImport(TransferHandler.TransferSupport support) {
            // for the demo, we'll only support drops (not clipboard paste)
            if (!support.isDrop()) {
                return false;
            }

            if (!support.isDataFlavorSupported(SongTransferable.objectFlavor)) {
                return false;
            }

            boolean actionSupported = (action & support.getSourceDropActions()) == action;
            if (actionSupported) {
                support.setDropAction(action);
                return true;
            }

            return false;
        }

        public boolean importData(TransferHandler.TransferSupport support) {
            // if we can't handle the import, say so
            if (!canImport(support)) {
                return false;
            }

            // fetch the drop location
            JList.DropLocation dl = (JList.DropLocation) support.getDropLocation();

            toIndex = dl.getIndex();

            // fetch the data and bail if this fails
            SlimPlayableObject data = null;
            try {
                data = (SlimPlayableObject) support.getTransferable().getTransferData(SongTransferable.objectFlavor);
            } catch (UnsupportedFlavorException e) {
                return false;
            } catch (java.io.IOException e) {
                return false;
            } catch (Exception e) {
                e.printStackTrace();
            }

            JList list = (JList) support.getComponent();
            DefaultListModel model = (DefaultListModel) list.getModel();


            if (data instanceof SlimPlaylistItem) {
                final SlimPlaylistItem toData = (SlimPlaylistItem) data;
                model.insertElementAt(toData, toIndex);
                try {
                    if (toIndex > fromIndex) {
                        playlist.move(toData, toIndex - 1);
                    } else {
                        playlist.move(toData, toIndex);
                    }
                } catch (SlimException ex) {
                    Logger.getLogger(PlaylistSongList.class.getName()).log(Level.SEVERE, null, ex);
                }
            } else {

                synchronized (playlist) {
                    try {
                        //add to playlist then move
                        playlist.addItem(data);
                        SlimPlaylistItem song = new SlimPlaylistItem(data);
                        song.setPlaylistIndex(getModel().getSize());
                        playlist.move(song, toIndex);                      
                        model.add(toIndex, song);

                    } catch (SlimException ex) {
                        Logger.getLogger(PlaylistSongList.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }


            Rectangle rect = list.getCellBounds(toIndex, toIndex);

            list.scrollRectToVisible(rect);

            list.setSelectedIndex(toIndex);

            list.requestFocusInWindow();
            return true;
        }
    }
}
